package com.imooc.business.core.executor.calculate;

import com.googlecode.aviator.AviatorEvaluator;
import com.imooc.module.collect.enums.DataTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Map;

/**
 * @Author Tim
 * @Description:
 * @Version 1.0
 */
@Slf4j
@Component
public class AviatorProcess implements ExpressionProcess{
    @Override
    public <T> T process(Class<T> javaType, String funExpression, Map<String, Object> params, Object defaultValue) {
        try {
            Object calculateValue = AviatorEvaluator.execute(funExpression, params);
            return buildValue(javaType, calculateValue);
        } catch (ArithmeticException e) {
            log.error("AviatorProcess process , e=", e);
            return javaType.cast(defaultValue);
        }
    }

    private <T> T buildValue(Class<T> javaType, Object calculateValue) {
        Object result = null;
        if (DataTypeEnum.INTEGER.getJavaType() == javaType) {
            result = adapterInteger(calculateValue);
        } else if (DataTypeEnum.LONG.getJavaType() == javaType) {
            result = adapterLong(calculateValue);
        } else if (DataTypeEnum.DOUBLE.getJavaType() == javaType) {
            result = adapterDouble(calculateValue);
        }
        return javaType.cast(result);
    }

    private Object adapterDouble(Object calculateValue) {
        Object result = calculateValue;
        if (calculateValue instanceof Long v) {
            result = v.doubleValue();
        } else if (calculateValue instanceof Double v) {
            result = v;
        } else if (calculateValue instanceof BigDecimal v) {
            result = v.doubleValue();
        } else if (calculateValue instanceof BigDecimal v) {
            result = v.doubleValue();
        }
        return result;
    }

    private Object adapterLong(Object calculateValue) {
        Object result = calculateValue;
        if (calculateValue instanceof Long v) {
            result = v;
        } else if (calculateValue instanceof Double v) {
            result = v.longValue();
        } else if (calculateValue instanceof BigDecimal v) {
            result = v.longValue();
        } else if (calculateValue instanceof BigDecimal v) {
            result = v.longValue();
        }
        return result;
    }

    /**
     * 将calculateValue适配成Integer类型
     * @param calculateValue
     * @return
     */
    private Object adapterInteger(Object calculateValue) {
        //整数 -> long ，浮点 -> double，大数 -> BigDecimal  BigInteger
        Object result = calculateValue;
        if (calculateValue instanceof Long v) {
            result = v.intValue();
        } else if (calculateValue instanceof Double v) {
            result = v.intValue();
        } else if (calculateValue instanceof BigDecimal v) {
            result = v.intValue();
        } else if (calculateValue instanceof BigDecimal v) {
            result = v.intValue();
        }
        return result;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
